package net.adetech.cjg.innerservice.controller;

import ch.qos.logback.core.util.Loader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.adetech.cjg.innerservice.entity.Qzb;
import net.adetech.cjg.innerservice.entity.Zd;
import net.adetech.cjg.innerservice.entity.Zdpc;
import net.adetech.cjg.innerservice.mapper.DepartDao;
import net.adetech.cjg.innerservice.mapper.QzbDao;
import net.adetech.cjg.innerservice.mapper.ZdDao;
import net.adetech.cjg.innerservice.mapper.ZdpcDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class MessageController {


    private static Map<String, List<JSONObject>> in2outMessageMap = new HashMap<>();
    private static Map<String, List<JSONObject>> out2inMessageMap = new HashMap<>();


    private static Object lock = new Object();

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ZdpcDao zdpcDao;


    public static Map<String, String> ipMap = null;


    private String getClientIp() {
        String remoteAddr = "";

        if (request != null) {
            remoteAddr = request.getHeader("X-FORWARDED-FOR");
            if (remoteAddr == null || "".equals(remoteAddr)) {
                remoteAddr = request.getRemoteAddr();
            }
        }
        return remoteAddr;
    }


    private String getClientId() {

        if (ipMap == null) {
            refreshZdList();
        }
        String clientId = ipMap.get(getClientIp());
        if (clientId == null) {
            clientId = "0";
        }
        return clientId;
    }

    public static String getClientId(String ip)
    {
        String clientId = ipMap.get(ip);
        if (clientId == null) {
            clientId = "0";
        }
        return clientId;
    }



    /**
     * 内屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/in2out", produces = "application/json")
    public String in2out(String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String result = getResponse(jsonObject, getClientId(), in2outMessageMap, out2inMessageMap);
        return result;
    }

    /**
     * 内屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/postOut", produces = "application/json")
    public String out(String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String type = jsonObject.getString("type");
        if ("clearView".equals(type))
        {
            int viewId = jsonObject.getInteger("viewId");
            if (viewId==10)
            {
                SqjlController.clearClientInfo(getClientId());
            }
        }
        return noResponse(jsonObject, getClientId(), in2outMessageMap);
    }


    /**
     * 外屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/out2in", produces = "application/json")
    public String out2in(@RequestBody String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        return getResponse(jsonObject, getClientId(), out2inMessageMap, in2outMessageMap);
    }


    /**
     * 外屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/postIn", produces = "application/json")
    public String in(@RequestBody String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String type = jsonObject.getString("type");

        if ("changeServiceType".equals(type)) {
            String serviceType = jsonObject.getString("serviceType");
            SqjlController.addServiceType(getClientId(), serviceType);
        } else if ("person1".equals(type) || "person2".equals(type)) {
            String zp = jsonObject.getString("zp");
            zp = transImage(zp);
            jsonObject.put("zp", zp);
            if ("person1".equals(type)) {
                SqjlController.addPerson1(getClientId(), jsonObject);

            }
            else if ("person2".equals(type)) {
                SqjlController.addPerson2(getClientId(), jsonObject);
            }
        }
        else if ("saveSign".equals(type)) {
            String signSrc = jsonObject.getString("src");
            SqjlController.addSignSrc(getClientId(), signSrc);
        }
        else if ("saveSign2".equals(type)) {
            String signSrc = jsonObject.getString("src");
            SqjlController.addSignSrc2(getClientId(), signSrc);
        }

        else if("saveInfo".equals(type))
        {
            String clientId = getClientId();
            SqjlController.clearClientInfo(clientId);
        }

        return noResponse(jsonObject, getClientId(), out2inMessageMap);
    }


    /**
     * 外屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/out2inJs", produces = "application/json")
    public String out2inJs(String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);


        return getResponse(jsonObject, getClientId(), out2inMessageMap, in2outMessageMap);
    }

    /**
     * 外屏页面调用
     *
     * @param msg
     * @return
     */
    @RequestMapping(value = "/cjg/postInJs", produces = "application/json")
    public String inJs(String msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg);
        String type = jsonObject.getString("type");
        if ("changeServiceType".equals(type)) {
            String serviceType = jsonObject.getString("serviceType");
            SqjlController.addServiceType(getClientId(), serviceType);
        } else if ("person1".equals(type) || "person2".equals(type)) {
            String zp = jsonObject.getString("zp");
            zp = transImage(zp);
            jsonObject.put("zp", zp);
            if ("person1".equals(type)) {
                SqjlController.addPerson1(getClientId(), jsonObject);

            }
            else if ("person2".equals(type)) {
                SqjlController.addPerson2(getClientId(), jsonObject);
            }
        }
        else if ("saveSign".equals(type)) {
            String signSrc = jsonObject.getString("src");
            SqjlController.addSignSrc(getClientId(), signSrc);
        }
        else if ("saveSign2".equals(type)) {
            String signSrc = jsonObject.getString("src");
            SqjlController.addSignSrc2(getClientId(), signSrc);
        }
        else if("saveInfo".equals(type))
        {
            String clientId = getClientId();
            SqjlController.clearClientInfo(clientId);
        }
        return noResponse(jsonObject, getClientId(), out2inMessageMap);
    }


    private String getResponse(JSONObject msg, String clientId, Map<String, List<JSONObject>> sendMessageMap, Map<String, List<JSONObject>> receiveMessageMap) {
        JSONObject nullJson = new JSONObject();
        nullJson.put("type", "null");
        String result = nullJson.toJSONString();

        synchronized (lock) {
            try {
                String type = msg.getString("type");
                if (!"null".equals(type)) {
                    List<JSONObject> sendMessageList = sendMessageMap.get(clientId);
                    if (sendMessageList == null) {
                        sendMessageList = new ArrayList<>();
                    }
                    if (sendMessageList.size() > 0) {
                        for (JSONObject msgJson : sendMessageList) {
                            if (type.equals(msgJson.getString("type"))) {
                                sendMessageList.remove(msgJson);
                                break;
                            }
                        }
                    }
                    sendMessageList.add(msg);
                    sendMessageMap.put(clientId, sendMessageList);
                }


                List<JSONObject> receiveMessageList = receiveMessageMap.get(clientId);
                if (receiveMessageList != null && receiveMessageList.size() > 0) {
                    JSONObject resultJson = receiveMessageList.get(0);
                    result = resultJson.toJSONString();
                    receiveMessageList.remove(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
                result = nullJson.toJSONString();
            }
        }
        return result;
    }

    private String noResponse(JSONObject msg, String clientId, Map<String, List<JSONObject>> sendMessageMap) {

        JSONObject nullJson = new JSONObject();
        nullJson.put("type", "null");
        String result = nullJson.toJSONString();
        synchronized (lock) {
            try {
                String type = msg.getString("type");
                if (!"null".equals(type)) {
                    List<JSONObject> sendMessageList = sendMessageMap.get(clientId);
                    if (sendMessageList == null) {
                        sendMessageList = new ArrayList<>();
                    }
                    for (JSONObject msgJson : sendMessageList) {
                        if (type.equals(msgJson.getString("type"))) {
                            sendMessageList.remove(msgJson);
                            break;
                        }
                    }
                    sendMessageList.add(msg);
                    sendMessageMap.put(clientId, sendMessageList);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }


    private void refreshZdList() {
//        List<Zd> zdList = zdDao.getAllZdList();
        List<Zdpc> zdpcList = zdpcDao.getAllZdList();
        ipMap = new HashMap<>();
        for (Zdpc zdpc : zdpcList
        ) {
            ipMap.put(zdpc.getZdip(), zdpc.getId()+"");
            ipMap.put(zdpc.getPcip(), zdpc.getId()+"");
        }
    }


    @RequestMapping(value = "/cjg/refreshIp")
    public String refreshIp() {
        refreshZdList();
        JSONObject result = new JSONObject();
        result.put("result", "ok");
        return result.toJSONString();
    }


    public String transImage(String zp) {
        String result = "";
        try {
            byte[] bytes1 = new BASE64Decoder().decodeBuffer(zp);
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
            BufferedImage bi = ImageIO.read(bais);
            Image image = (Image) bi;
            ImageIcon imageIcon = new ImageIcon(image);
            BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                    BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
            g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
            int alpha = 0;
            for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) {
                for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) {
                    int rgb = bufferedImage.getRGB(j2, j1);

                    int R = (rgb & 0xff0000) >> 16;
                    int G = (rgb & 0xff00) >> 8;
                    int B = (rgb & 0xff);
                    if (((255 - R) < 12) && ((255 - G) < 12) && ((255 - B) < 12)) {
                        rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff);
                    }

                    bufferedImage.setRGB(j2, j1, rgb);

                }
            }

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(bufferedImage, "png", baos);
            byte[] bytes = baos.toByteArray();
            result = new BASE64Encoder().encode(bytes);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }


    private static Map<String,JSONObject> loginInfoMap = new HashMap<>();
    private static Map<String,String> signMap = new HashMap<>();

    @Autowired
    private DepartDao departDao;

    @RequestMapping(value = "/cjg/login",produces = "application/json")
    public String login(String yhzh,String yhm,String orgCode)
    {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("yhzh",yhzh);
        jsonObject.put("yhm",yhm);
        String clientId = getClientId();
        jsonObject.put("clientId",clientId);
        loginInfoMap.put(clientId,jsonObject);
        Qzb qzb = qzbDao.getQmbByYhzh(yhzh);

        if (qzb!=null)
        {
            jsonObject.put("signSrc",qzb.getQzImg());

        }

        if (orgCode!=null)
        {
            String glbm = departDao.getGlbm(orgCode);
            String xzqhShi = glbm.substring(0,4)+"00";
            jsonObject.put("xzqhShi",xzqhShi);
            jsonObject.put("glbm",glbm);
        }


        return jsonObject.toJSONString();
    }



    @Value("${app.domain}")
    private String appDomain;






    @Autowired
    QzbDao qzbDao;



    @RequestMapping(value = "/cjg/saveMySign",produces = "application/json")
    public String saveMySign(String src)
    {

        String clientId = getClientId();
        JSONObject loginJson = loginInfoMap.get(clientId);
        String yhm = loginJson.getString("yhm");
        String yhzh = loginJson.getString("yhzh");
        signMap.put(clientId,src);
        Qzb qzb = qzbDao.getQmbByYhzh(yhzh);
        if (qzb==null)
        {
            qzb = new Qzb();
            qzb.setYhzh(yhzh);
            qzb.setYhm(yhm);
            qzb.setQzImg(src);
            qzbDao.newQz(qzb);
        }
        else {
            qzb.setQzImg(src);
            qzbDao.updateQz(qzb);
        }

        signMap.put(clientId,src);


        JSONObject resultJson = new JSONObject();
        resultJson.put("result","ok");
        return resultJson.toJSONString();
    }

    private static Object lock2 = new Object();
    @RequestMapping(value = "/cjg/loadMySign",produces = "application/json")
    public String loadMySign(){
        String clientId = getClientId();
        JSONObject resultObject = new JSONObject();
        resultObject.put("result","none");
        synchronized (lock2)
        {
            String src = signMap.get(clientId);
            if (src!=null)
            {
                resultObject.put("result","new");
                resultObject.put("src",src);
                signMap.remove(clientId);
            }
        }
        return resultObject.toJSONString();
    }

    @RequestMapping(value = "/cjg/getMySign",produces = "application/json")
    public String mySign()
    {
        String clientId = getClientId();
        JSONObject loginJson = loginInfoMap.get(clientId);
        String yhzh = loginJson.getString("yhzh");
        Qzb qzb = qzbDao.getQmbByYhzh(yhzh);
        return JSONObject.toJSONString(qzb);
    }



}
